﻿using System;
using System.Collections;
using System.Collections.Generic;
using LitJson;
using UnityEngine;

namespace YummyGame.Framework
{
    public enum SkillDescriptorFieldType
    {
        Number,
        String,
        Struct
    }

    public class SkillKeyValuePair
    {
        public string key { get; private set; }
        public SkillDescriptorField field { get; private set; }
        public int depth { get; private set; }
        public SkillKeyValuePair(string key,JsonData data,int depth)
        {
            this.key = key;
            this.depth = depth;
            this.field = new SkillDescriptorField(data, depth);
        }

    }

    public class SkillDescriptorField
    {
        private JsonData data;
        public SkillDescriptorFieldType type { get; private set; }
        public string str_value { get; private set; }
        public float number_value { get; private set; }
        public object obj_value { get; private set; }
        public List<SkillKeyValuePair> pairs = new List<SkillKeyValuePair>();
        public int depth { get; private set; }
        public SkillDescriptorField(JsonData data,int depth)
        {
            this.data = data;
            this.depth = depth;
            if (data.IsInt)
            {
                number_value = data.ValueAsInt();
                type = SkillDescriptorFieldType.Number;
            }else if (data.IsDouble)
            {
                number_value = (float)data.ValueAsDouble();
                type = SkillDescriptorFieldType.Number;
            }else if (data.IsLong)
            {
                number_value = (long)data.ValueAsLong();
                type = SkillDescriptorFieldType.Number;
            }else if (data.IsString)
            {
                str_value = data.ValueAsString();
                type = SkillDescriptorFieldType.String;
            }else if (data.IsObject)
            {
                type = SkillDescriptorFieldType.Struct;
                IDictionary dic = (IDictionary)data;
                foreach (string key in dic.Keys)
                {
                    pairs.Add(new SkillKeyValuePair(key, data[key], depth+1));
                }
            }

        }
        public bool IsStruct()
        {
            return type == SkillDescriptorFieldType.Struct;
        }

        public bool IsString()
        {
            return type == SkillDescriptorFieldType.String;
        }

        public string AsString()
        {
            if (!IsString()) throw new Exception("类型错误");
            return str_value;
        }


        public bool IsNumber()
        {
            return type == SkillDescriptorFieldType.Number;
        }

        public float AsNumber()
        {
            if (!IsNumber()) throw new Exception("类型错误");
            return number_value;
        }

        public SkillKeyValuePair GetChildPair(string name)
        {
            foreach (var pair in pairs)
            {
                if (pair.key == name) return pair;
            }
            return null;
        }

        public SkillDescriptorField GetChildField(string name)
        {
            var pair = GetChildPair(name);
            if (pair != null) return pair.field;
            return null;
        }
    }
    public class SkillDescriptor
    {
        public SkillDescriptor extends { get; private set; }
        public string fullPath { get; private set; }
        private SkillKeyValuePair root;
        private SkillPrototype _prototype;


        public SkillPrototype GetPrototype()
        {
            if (_prototype == null)
            {
                _prototype = new SkillPrototype(this);
            }
            return _prototype;
        }

        public SkillDescriptor(string path)
        {
            JsonData data = JsonMapper.ToObject(Skill.Loader(path));
            this.fullPath = path;
            IDictionary dic = (IDictionary)data;
            foreach (string rootkey in dic.Keys)
            {
                root = new SkillKeyValuePair(rootkey, data[rootkey],0);
                break;
            }
            var extendField = GetBaseInfo().field.GetChildField(SkillKeyword.base_info_extends);
            if (extendField != null && extendField.IsString())
            {
                extends = new SkillDescriptor(extendField.AsString());
            }
        }

        public SkillKeyValuePair GetVariable()
        {
            return GetInfo(SkillKeyword.variable, 1);
        }


        public SkillKeyValuePair GetExpression()
        {
            return GetInfo(SkillKeyword.expression, 1);
        }

        public SkillKeyValuePair GetEffect()
        {
            return GetInfo(SkillKeyword.effect, 1);
        }

        public SkillKeyValuePair GetBaseInfo()
        {
            return GetInfo(SkillKeyword.base_info, 1);
        }

        public SkillKeyValuePair GetInfo(string key,int depth)
        {
            return _GetInfo(key, root, depth, 0);
        }

        private SkillKeyValuePair _GetInfo(string key, SkillKeyValuePair pair, int depth,int current)
        {
            if (pair.key == key) return pair;
            if (depth == current) return null;
            foreach (var next in pair.field.pairs)
            {
                SkillKeyValuePair res = _GetInfo(key, next, depth, current + 1);
                if (res != null) return res;
            }
            return null;
        }
    }
}
